P03-1. 2세대 Ambient Mesh 혁명 - ztunnel과 Waypoint - 이론 개념
Part 03 (이론): 2세대 Ambient Mesh 혁명 — ztunnel · HBONE · Waypoint
- 1세대 사이드카(Sidecar) 아키텍처가 가진 4가지 구조적 한계를 해결하기 위해 왜 데이터 플레인을 L4 계층(
ztunnel)과 L7 계층(Waypoint)으로 2단 분리했는지 설명할 수 있다. - 파드 안에 사이드카나
istio-init컨테이너를 전혀 넣지 않고(READY 1/1), 노드당 1개씩 뜨는istio-cni-node와 Rust 기반ztunnel이 어떻게 파드의 트래픽을 가로채는지(In-Pod Redirection) 이해한다. - Ambient Mesh의 핵심 통신 규약인
HBONE(HTTP-Based Overlay Network Environment, 포트15008) 이 왜 일반 TCP가 아닌 HTTP/2CONNECT터널 위에서 동작하는지 원리를 파악한다. - L4 보안/암호화만 필요할 때의 통신 경로(
ztunnel직통)와, L7 라우팅/인가가 필요할 때의 통신 경로(Waypoint Proxy경유)의 차이를 비교할 수 있다.
1. 왜 사이드카(Sidecar)를 파드 밖으로 쫓아냈을까?
Part 02에서 우리는 1세대 사이드카 메시가 얼마나 정교한 iptables 마법으로 동작하는지 살펴보았습니다. 하지만 동시에 현업 인프라에서 사이드카를 수백~수천 개 파드에 적용할 때 겪는 4가지 치명적인 고통도 확인했습니다.
- 메모리·CPU의
중복 낭비: 파드가 500개면 C++로 만들어진 무거운 Envoy 프록시도 500개가 떠서 수십 GB의 메모리를 그냥 먹어 치웁니다. - 파드 재시작 강제: 네임스페이스에 메시를 적용하거나 Envoy 버전을 패치할 때마다 비즈니스 애플리케이션 파드 전체를 재시작(
rollout restart) 해야 합니다. istio-init의 보안 특권(NET_ADMIN)과 기동 순서 충돌: 모든 파드마다 방화벽 관리자 권한을 가진 초기화 컨테이너가 실행되어야 하고, 앱이 사이드카보다 먼저 외부 DB에 접속하려 하면 기동 에러가 터집니다.- L7 과잉 스펙(Over-engineering): 실무에서 서비스 메시를 도입하는 기업의 70% 이상은 "파드 간 통신을 mTLS로 암호화하고 출입 통제(Zero-Trust 보안)만 하고 싶을 뿐" 인데도, 무조건 무거운 L7(HTTP/gRPC) 파서 엔진까지 통째로 들어 있는 Envoy를 모든 파드마다 붙여야 했습니다.
이 문제를 뿌리부터 해결하기 위해 Istio가 선보인 2세대 아키텍처가 바로 Ambient Mesh(앰비언트 메시) 입니다.
- Ambient(앰비언트): 영어로 "주변에 깔려 있는, 공기처럼 둘러싼" 이라는 뜻입니다(예: 은은하게 방 전체를 비추는 간접 조명을 Ambient Light라고 부릅니다).
- 왜 이름이 Ambient Mesh인가요?: 1세대처럼 프록시를 파드라는 방 안(
containers)에 억지로 밀어 넣는 대신, 프록시를 쿠버네티스 노드(바닥 인프라)에 공기처럼 깔아 두고 파드는 자기 몸에 아무것도 붙이지 않은 채(READY 1/1) 그 위에서 자연스럽게 암호화·라우팅 혜택을 누린다는 뜻에서 붙은 이름입니다.
2. Ambient Mesh의 핵심 철학: L4(보안 수송)와 L7(정밀 검문)의 2계층 분리
Ambient Mesh가 사이드카를 없애면서 내세운 가장 천재적인 아이디어는 "모든 파드가 매번 무거운 L7(HTTP 본문/헤더) 검문을 할 필요는 없다! 데이터 플레인을 가벼운 L4 계층과 똑똑한 L7 계층으로 쪼개자!" 는 것입니다.
이해를 돕기 위해 대단지 아파트의 보안 시스템으로 비유해 보겠습니다.
- 1세대 사이드카 방식 (세대별 전담 경호원 + 동시통역사 상주):
원룸 세대(Pod)가 1,000세대 있으면, 1,000명의 경호원 겸 동시통역사(Envoy)를 고용해 각 원룸 방 안에 한 명씩 같이 살게 하는 것입니다. 주민이 옆집에 밀봉된 소포 하나만 보내려 해도 방 안의 통역사가 소포를 일일이 뜯어 내용물(L7 HTTP)을 다 읽고 번역합니다. 관리비가 폭발할 수밖에 없습니다. - 2세대 Ambient 방식 (동별 1층 로비 보안요원
ztunnel+ 단지 내 컨시어지 센터Waypoint):- 1층 로비 보안요원 (
ztunnel— L4 Secure Overlay): 각 원룸 방 안에는 아무도 넣지 않습니다(READY 1/1). 대신 아파트 동(Node)마다 1층 로비에 딱 1명의 초고속 보안요원(ztunnel) 만 배치합니다. 이 보안요원은 소포 안의 편지 내용(L7)은 읽지 않습니다. 오직 "보내는 세대와 받는 세대의 주민증(SPIFFE 인증서)이 진짜인가?" 만 확인한 뒤, 소포를 방탄 캡슐(HBONE)에 넣어 상대방 아파트 동 1층 로비로 총알처럼 쏴줍니다. - 컨시어지 센터 (
Waypoint Proxy— L7 Processing): 만약 특정 동네(Namespace)나 상가(Service)에서 "편지 봉투에/admin이라고 적힌 문서는 차단해 줘!" 혹은 "신규 상점으로 손님을 90:10 비율로 나눠 줘!" 같은 고급 통역·분류 작업(L7) 이 필요해지면 어떻게 할까요? 그때만 단지 한가운데에 전담 컨시어지 데스크(Waypoint Proxy)를 딱 1개 세우고, 1층 보안요원(ztunnel)에게 "저 상가로 가는 캡슐은 컨시어지 데스크를 한 번 거쳐서 보내라" 고 지시합니다!
- 1층 로비 보안요원 (
flowchart TB
subgraph GEN1["1세대 Sidecar Mesh (파드마다 무거운 L4+L7 Envoy 동거)"]
direction LR
P1["Pod A (READY 2/2)
App + Envoy (L4+L7)"] -->|"mTLS"| P2["Pod B (READY 2/2)
App + Envoy (L4+L7)"]
P3["Pod C (READY 2/2)
App + Envoy (L4+L7)"] -->|"mTLS"| P2
end
subgraph GEN2["2세대 Ambient Mesh (노드당 1개 L4 ztunnel + 필요할 때만 L7 Waypoint)"]
direction LR
subgraph NODE1["Worker Node 1"]
A1["Pod A (READY 1/1)
순수 App만 실행"] --> Z1["ztunnel (DaemonSet)
초경량 Rust L4 프록시"]
A2["Pod C (READY 1/1)
순수 App만 실행"] --> Z1
end
subgraph NODE2["Worker Node 2"]
Z2["ztunnel (DaemonSet)
초경량 Rust L4 프록시"] --> B1["Pod B (READY 1/1)
순수 App만 실행"]
WP["Waypoint Proxy (선택)
L7 기능이 필요할 때만 배포"]
end
Z1 -->|"1. 기본 L4 통신: HBONE (:15008) 직통"| Z2
Z1 -.->|"2. L7 정책 필요 시: Waypoint 경유"| WP
WP -.->|"HBONE (:15008)"| Z2
end
ztunnel(Zero-Trust Tunnel):- 쿠버네티스의 모든 워커 노드마다 정확히 1개씩만 실행되는(
DaemonSet) L4 전용 초경량 프록시입니다. - 무거운 C++ Envoy 대신 메모리 안전성과 속도가 뛰어난 Rust 언어로 처음부터 새로 작성되었습니다. HTTP 파서 같은 무거운 L7 코드를 완전히 덜어내고 오직 mTLS 암호화, SPIFFE 인증서 검증, L4 접근 제어, TCP 메트릭 수집, HBONE 터널링만 수행하므로 메모리 사용량이 사이드카 대비 1/10 수준으로 극히 적습니다.
- 쿠버네티스의 모든 워커 노드마다 정확히 1개씩만 실행되는(
istio-cni-node(Istio CNI 플러그인 DaemonSet):- 각 워커 노드마다 1개씩 떠서, 해당 노드에 있는 파드들 중 Ambient 메시에 등록된 파드를 찾아내어 파드와
ztunnel사이의 네트워크 길(리다이렉션)을 자동으로 연결해 주는 배관공입니다. 이 CNI 데몬 덕분에 파드 안에istio-init초기화 컨테이너를 넣거나 파드를 재시작할 필요가 전혀 없습니다!
- 각 워커 노드마다 1개씩 떠서, 해당 노드에 있는 파드들 중 Ambient 메시에 등록된 파드를 찾아내어 파드와
Waypoint Proxy(웨이포인트 프록시):- URL 경로별 라우팅, 헤더 기반 카나리 배포(90:10), HTTP 메서드(
GET/DELETE)별 인가 정책, 서킷 브레이커 같은 L7 기능이 실제로 필요한 네임스페이스나 서비스에만 선택적으로 띄우는 Envoy 기반 L7 전용 프록시 파드입니다.
- URL 경로별 라우팅, 헤더 기반 카나리 배포(90:10), HTTP 메서드(
3. 핵심 기술 해부 ①: 파드를 재시작하지도 않았는데 어떻게 패킷을 가로채나요? (In-Pod Redirection)
여기서 아주 날카로운 질문이 하나 생깁니다.
"1세대에서는 파드를 만들 때 istio-init 컨테이너가 들어가서 방화벽(iptables)을 고쳤잖아요. 그런데 2세대 Ambient에서는 이미 떠서 돌아가고 있는 파드를 재시작하지도 않고, 네임스페이스에 istio.io/dataplane-mode=ambient 라벨만 딱 붙이면 그 순간부터 즉시 ztunnel이 패킷을 가로챕니다. 이게 리눅스 커널에서 어떻게 가능한가요?"
비밀은 Part 02 실습의 Step 3에서 우리가 직접 써먹었던 네트워크 네임스페이스(NetNS) 진입 기술에 있습니다!
sequenceDiagram
autonumber
participant User as 관리자 (kubectl label)
participant CNI as istio-cni-node
(노드 배관공 DaemonSet)
participant NetNS as 앱 파드의 NetNS
(커널 네트워크 방)
participant ZT as ztunnel
(노드 L4 프록시 DaemonSet)
User->>CNI: 네임스페이스에 istio.io/dataplane-mode=ambient 라벨 부여
CNI->>NetNS: 1. 호스트 권한으로 실행 중인 파드의 NetNS에 직접 진입!
파드 방 안에 iptables/규칙 설치 (15001, 15006, 15008)
CNI->>ZT: 2. Unix Domain Socket(ZDS)을 통해
파드 NetNS의 파일 디스크립터(방 열쇠)를 ztunnel에게 전달!
ZT->>NetNS: 3. ztunnel 프로세스는 노드에서 1개만 돌지만,
소켓(15001, 15006, 15008)은 파드 NetNS 방 안쪽에 직접 생성!
Note over NetNS,ZT: 결과: 파드 재시작 없이 즉시 암호화 터널 개통 완료!- 배관공(
istio-cni-node)의 즉시 침투: 우리가 네임스페이스에istio.io/dataplane-mode=ambient라벨을 붙이는 순간, 노드의 관리자 권한을 가진istio-cni-node가 그 노드 위에서 돌고 있는 대상 파드들의 네트워크 방(NetNS)에 밖에서 직접 문을 열고 들어갑니다(우리가 Part 02에서nsenter로 들어간 것과 똑같은 원리입니다!). 따라서 파드를 껐다 켤 필요가 전혀 없습니다. - 방 열쇠 전달(
ZDS, ztunnel Discovery Service):istio-cni-node는 파드 방 안에 리다이렉션 규칙을 세팅한 뒤, 그 파드 네트워크 방의 열쇠(Linux File Descriptor)를 같은 노드의ztunnel에게 건네줍니다. ztunnel의 마법 (In-Pod Socket Listening):ztunnel프로그램 자체는 노드 전체에 딱 1개만 떠서 돌아가지만, 전달받은 방 열쇠를 이용해 각 앱 파드의 네트워크 방(NetNS) 안쪽에 직접 자기 귀(15001,15006,15008리스닝 소켓)를 열어 둡니다!- 덕분에 앱 파드에서 나가는 패킷은 노드 밖으로 노출되기도 전에 파드 방 안에서 즉시
ztunnel의 소켓으로 빨려 들어가며, 같은 노드에 있는 다른 악성 파드가 중간에 패킷을 훔쳐보거나 위조하는 것이 원천적으로 불가능합니다.
- 덕분에 앱 파드에서 나가는 패킷은 노드 밖으로 노출되기도 전에 파드 방 안에서 즉시
4. 핵심 기술 해부 ②: HBONE (:15008) — HTTP/2 위에 세운 비밀 지하차도
클라이언트 노드의 ztunnel이 앱 파드의 패킷을 받아서 상대방 서버 노드의 ztunnel로 보낼 때, 그냥 일반 TCP로 보내지 않고 HBONE (HTTP-Based Overlay Network Environment) 이라는 특수 규약을 사용해 무조건 15008번 포트로 묶어서 보냅니다.
HBONE 과 HTTP/2 CONNECT
- Overlay Network (오버레이 네트워크): 기존에 깔려 있는 일반 도로(노드 간 물리/가상 네트워크) 위에, 우리끼리만 통하는 가상의 고가도로나 지하 터널을 한 겹 더 씌운 네트워크를 뜻합니다.
- HTTP/2
CONNECT메서드: 원래 웹 브라우저가 프록시 서버에게 "나 저 목적지 서버랑 암호화 통신을 해야 하니, 네가 중간에서 데이터는 뜯어보지 말고 그냥 양쪽 파이프만 직결(터널링)해 줘!" 라고 요청할 때 쓰는 표준 HTTP 명령입니다. 여기에 HTTP/2의 멀티플렉싱(Multiplexing) 기능이 결합되면, 단 1개의 mTLS 암호화 연결(:15008) 안에 수백 개의 서로 다른 파드 통신 스트림을 동시에 실어 나를 수 있는 초고속 다차선 방탄 터널이 됩니다. HBONE(HTTP-Based Overlay Network Environment): Istio Ambient Mesh가 노드 간(ztunnel↔ztunnel), 또는ztunnel↔Waypoint간에 패킷을 주고받을 때 사용하는 표준 프로토콜입니다. 포트 번호는 항상15008번을 사용하며, 겉포장은 mTLS(SPIFFE 인증서)로 암호화된 HTTP/2CONNECT터널이고 그 터널 안쪽에는 원래 앱이 보낸 순수 TCP 패킷이 그대로 들어 있습니다.
왜 굳이 HBONE(:15008) 터널에 싸서 보낼까요?
flowchart LR
subgraph NODE_A["desktop-worker2 (클라이언트 노드)"]
APP_A["study-client 파드
(10.244.1.x)
curl http://order-api:80"] -->|"평문 TCP"| ZT_A["Node 2 ztunnel
출발지 신분증(SPIFFE) 서명"]
end
subgraph HBONE_TUNNEL["HBONE 터널 (TCP 15008 포트 · mTLS 암호화 · HTTP/2 CONNECT)"]
HEADER["[HTTP/2 CONNECT 헤더]
:authority = 10.244.2.x:8080
x-forwarded-client-cert = spiffe://.../sa/default
────────────────────
[내부 페이로드]
원본 GET / HTTP/1.1 패킷"]
end
subgraph NODE_B["desktop-worker (서버 노드)"]
ZT_B["Node 1 ztunnel (:15008)
mTLS 검증 및 캡슐 해제"] -->|"평문 TCP (:8080)"| APP_B["order-api 파드
(10.244.2.x:8080)"]
end
ZT_A ==>|"15008 포트로 암호화 전송"| HBONE_TUNNEL ==>|"15008 포트 수신"| ZT_B- 원래 목적지 포트(
:8080)와 출발지 신분(SPIFFE)을 안전하게 배달하기 위해:
모든 암호화 통신을15008번 포트 하나로 통일해 보내더라도, 터널을 열 때 HTTP/2CONNECT헤더(:authority: 10.244.2.x:8080)에 "이 캡슐 안에 든 패킷은 사실10.244.2.x파드의8080번 포트로 가던 녀석이야!" 라고 적어서 보낼 수 있습니다. 받는 쪽ztunnel은15008번으로 캡슐을 받은 뒤 헤더를 보고 정확히order-api파드의8080번 포트로 패킷을 넣어 줍니다. - 어떤 클라우드(AWS, KT Cloud, NCP) 방화벽이든 100% 통과하기 위해:
전통적인 커널 오버레이 네트워크(VXLAN, Geneve 등)는 특수한 UDP 헤더를 쓰기 때문에 클라우드 VPC 보안 그룹이나 방화벽에서 막히는 경우가 많습니다. 반면HBONE은 겉보기에 가장 표준적인 TCP15008번 포트의 일반 TLS(HTTPS/2) 통신이므로, 어떤 클라우드나 하이브리드 VM 환경에서도 방화벽 충돌 없이 100% 그대로 통과합니다!
5. 핵심 기술 해부 ③: L7 기능이 필요할 때 등장하는 Waypoint Proxy
ztunnel만으로도 파드 간 mTLS 암호화와 L4 접근 제어(누가 누구에게 접속할 수 있는가) 는 완벽하게 해결됩니다.
하지만 다음과 같은 L7(애플리케이션 계층) 작업이 필요할 때는 ztunnel만으로는 불가능합니다.
- "HTTP
GET요청은 허용하고DELETE요청은 차단해라" (L7 AuthorizationPolicy) - "
/v2경로로 오는 요청이나 특정 헤더가 있는 요청만 신규 버전 파드로 보내라" (L7 HTTPRoute) - "응답이 500 에러가 나면 자동으로 3번 재시도(Retry)해라"
이때 우리는 istioctl waypoint apply 명령 한 줄(또는 쿠버네티스 표준 Gateway YAML)로 해당 네임스페이스 전용 L7 검문소인 Waypoint Proxy 를 띄웁니다.
Gateway API 와 Waypoint
- Kubernetes
Gateway API: 과거 쿠버네티스의 낡은Ingress리소스를 대체하고 서비스 메시 트래픽 제어까지 하나로 통합하기 위해 쿠버네티스 공식 표준으로 제정된 차세대 네트워크 API(Gateway,HTTPRoute,GRPCRoute등)입니다. - Istio Ambient와 Gateway API의 결합: 1세대 Istio에서는 무언가를 설정할 때마다 Istio 전용 문법(
VirtualService,DestinationRule)만 써야 했지만, 2세대 Ambient Mesh에서는Waypoint Proxy자체가 쿠버네티스 표준Gateway리소스(gatewayClassName: istio-waypoint)로 생성됩니다! 즉, 쿠버네티스 표준 문법만 배워도 서비스 메시를 제어할 수 있게 표준화되었습니다.
Waypoint Proxy가 추가되었을 때의 패킷 흐름 (2-Hop HBONE)
네임스페이스에 Waypoint를 등록(istio.io/use-waypoint=waypoint)하면, istiod 본부가 모든 노드의 ztunnel에게 이렇게 지시합니다:
"앞으로
part1-demo네임스페이스의 서비스(order-api)로 가는 패킷은 서버 노드로 바로 쏘지 말고, 무조건waypoint프록시 파드로 먼저 보내서 L7 검문을 받게 해라!"
study-client파드가http://order-api/headers를 호출합니다.- 클라이언트 노드의
ztunnel이 패킷을 잡아,order-api로 바로 보내는 대신waypoint파드의15008포트(HBONE) 로 먼저 보냅니다. waypoint프록시(Envoy)가 HBONE 캡슐을 열어 L7 정책 검사(URL 경로, HTTP 메서드, 카나리 가중치, L7 메트릭 측정) 를 수행한 뒤, 최종 선택된order-api파드가 있는 서버 노드의ztunnel(15008포트)로 다시 HBONE 캡슐을 쏴줍니다.- 서버 노드의
ztunnel이 캡슐을 벗겨order-api파드의:8080포트로 평문 전달합니다.
6. 한눈에 비교하는 1세대 Sidecar vs 2세대 Ambient Mesh
| 비교 항목 | 1세대 Sidecar Mesh (profile=default) |
2세대 Ambient Mesh (profile=ambient) |
|---|---|---|
파드당 컨테이너 개수 (READY) |
2/2 (앱 컨테이너 + istio-proxy) |
1/1 (순수 앱 컨테이너만 실행!) |
초기화 컨테이너 (istio-init) |
파드마다 주입됨 (NET_ADMIN 권한 필요) |
없음 (노드의 istio-cni-node가 외부에서 처리) |
| 메시 적용/해제 시 파드 재시작 | 필수 (rollout restart 해야 사이드카가 붙거나 빠짐) |
불필요 (라벨만 바꾸면 실행 중인 파드에 무중단 즉시 반영!) |
| L4 보안·암호화 담당 | 각 파드 안의 무거운 C++ Envoy | 노드당 1개만 뜨는 초경량 Rust ztunnel (DaemonSet) |
| L7 라우팅·정책 담당 | 각 파드 안의 무거운 C++ Envoy | 필요한 네임스페이스/서비스에만 띄우는 Waypoint Proxy |
| 노드 간 암호화 프로토콜 | 원래 목적지 포트로 직접 mTLS 연결 | HBONE (TCP 15008 포트, HTTP/2 CONNECT 멀티플렉싱 터널) |
| 프록시 버전 업그레이드 영향 | 모든 앱 파드를 재시작해야 Envoy가 업데이트됨 | 앱 파드 건드리지 않고 ztunnel DaemonSet / Waypoint만 교체 |
🔗 다음 단계 (실습 검증)
이론으로 배운 Ambient Mesh의 3총사(istio-cni-node, ztunnel, Waypoint Proxy)를 이제 우리의 docker-desktop 3노드 클러스터에 직접 설치하고, part1-demo 파드들에서 사이드카를 완전히 떼어낸 뒤(READY 1/1)에도 워커 노드 간 HBONE(:15008) mTLS 암호화 터널링이 완벽히 동작하는 모습을 눈으로 확인해 봅니다!
네비게이션
| 이전 | 목록 | 다음 |
|---|---|---|
| ◀ Part 02 실습 | 목록으로 | Part 03 실습 ▶ |